package org.weso.desempleo.model;


import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;

public abstract class Charger <T, S>{
	
	protected String[][] months = new String[12][2];
	public static final int CHARGER_SECTOR = 0;
	public static final int CHARGER_GENERO = 1;
	public static final int CHARGER_EDAD = 2;
	public static final int CHARGER_CONCEJO = 3;
	public static final int CHARGER_MUNICIPIO = 4;
	
	 /**
		 * This method initialize an Array with all months to let the servlet 
		 * calculate its numeric value.
		 */
		protected void initializeMonths() {
			months[0][0] = "Enero";
			months[0][1] = "January";
			months[1][0] = "Febrero";
			months[1][1] = "February";
			months[2][0] = "Marzo";
			months[2][1] = "March";
			months[3][0] = "Abril";
			months[3][1] = "April";
			months[4][0] = "Mayo";
			months[4][1] = "May";
			months[5][0] = "Junio";
			months[5][1] = "June";
			months[6][0] = "Julio";
			months[6][1] = "July";
			months[7][0] = "Agosto";
			months[7][1] = "August";
			months[8][0] = "Septiembre";
			months[8][1] = "September";
			months[9][0] = "Octubre";
			months[9][1] = "October";
			months[10][0] = "Noviembre";
			months[10][1] = "November";
			months[11][0] = "Diciembre";
			months[11][1] = "December";		
		}
		
		public static Charger getInstance(int type) 
						throws Exception {
			switch(type) {
				case CHARGER_SECTOR:
					return new ChargerSectors();
				case CHARGER_GENERO:
					return new ChargerGeneros();
				case CHARGER_EDAD:
					return new ChargerEdades();
				case CHARGER_CONCEJO:
					return new ChargerConcejo();
				case CHARGER_MUNICIPIO:
					return new ChargerMunicipio();
				default:
					throw new Exception("Tipo de cargador equivocado");					
			}
		}
		
		/**
		 * This method prepare a SPARQL query to obtain the value of the variable
		 * 'month' when the user change the language of exhibit page.
		 * @param month The value of month that the user has selected in the form.
		 * @param newLang The new language that the user has selected in the 
		 * exhibit page.
		 * @param oldLang The old language of exhibit page.
		 * @return The SPARQL query.
		 */
		private String prepareLanguageQuery(String month, String newLang,
				String oldLang) {
			return "PREFIX o: <http://purl.org/observatory/observatory.owl#>\n" + 
					"SELECT DISTINCT ?oldMonth ?newMonth FROM <http://purl.org/weso/testObservatory/observatoryBySectors/>" + 
					"WHERE {?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>" +
					"<http://purl.org/linked-data/cube#Observation>; o:refMonth ?oldMonth;" + 
					"o:refMonth ?newMonth \n FILTER (langMatches(lang(?oldMonth), \"" + oldLang + "\") && str(?oldMonth) =\"" + month + "\")" + 
					"FILTER (langMatches(lang(?newMonth), \"" + newLang + "\"))}";
		}
		
		/**
		 * This method obtain the value of variable 'month' when the user change
		 * the language of exhibit page.
		 * @param month The value of month that user select in the form.
		 * @param newLang The new language that user select.
		 * @param oldLang The old language
		 * @return The new value of variable 'month'
		 */
		protected String getNewMonth(String month, String newLang, String oldLang) {
			if(month.equals("Todos") || month.equals("All"))
				return month;
			else {
				String query = prepareLanguageQuery(month, newLang, oldLang);
				QueryExecution qExec = initializeQuery("http://156.35.31.156/sparql", query);
				ResultSet result = qExec.execSelect();
				if(result.hasNext()){
					QuerySolution solution = result.next();
					String sol = solution.get("newMonth").toString(); 
					return sol.substring(0, sol.indexOf('@'));				
				}
				return month;
			}
		}
		

		public abstract T obtain(String lang, String anyo, 
		    		String month, String selector, String langAnt);
		
		public abstract S extractData(QuerySolution sol, int observaciones);
		
		public abstract T processResult(ResultSet result);
		
		/**
		 * This method initialize an Object of type QueryExecution with the SPARQL
		 * query and RDF graph.
		 * @param graph The RDF graph which has to perform the query.
		 * @param query The SPRQL query.
		 * @return The QueryExecution object with the SPARQL query.
		 */
		public QueryExecution initializeQuery(String graph, String query) {
			QueryExecution qExec = QueryExecutionFactory.sparqlService(
					graph, query);
			return qExec;
		}
		
		public abstract String prepareSparqlQuery(String anyo, String selector, String month,
				String lang);
		
		/**
		 * This method parse the variable 'month' to obtain a part of the SPARL 
		 * query.
		 * @param month The value of month that the user has selected in the form.
		 * @return A part of the SPARQL query.
		 */
		protected String parseMonth(String month) {
			if(month.equals("Todos") || month.equals("All"))
				return "";
			return "&& str(?month)=\""+ month +"\"";
		}
		
		/**
		 * This method parse the variable 'anyo' to obtain a part of the SPARL 
		 * query.
		 * @param anyo The value of year that the user has selected in the form.
		 * @return A part of the SPARQL query.
		 */
		protected String parseYear(String anyo) {
			if(anyo.equals("Todos") || anyo.equals("All"))
				return ".";
			return ";o:refYear \"" + anyo + "\"";
		}
		
		/**
		 * This method obtain the numeric value (mm) of a determinate month.
		 * @param The month to calculate its numeric value.
		 * @return The numeric value (mm) of the month.
		 */
		public String extractMonth(String string) {
			for(int i = 0; i < months.length; i++) {
				for(int j = 0; j < months[0].length; j++) {
					if(months[i][j].equals(string)) {
						return ((i + 1) < 10?"0":"")+String.valueOf(i + 1);
					}
				}
			}
			return "";
		}

}
